# == Schema Information
#
# Table name: projects
#
#  id              :integer          not null, primary key
#  name            :string(255)
#  full_path       :string(255)
#  production      :boolean
#  name_a_host     :string(255)
#  local_key_path  :string(255)
#  restart_command :string(255)
#  restart_sh      :string(255)
#  start_command   :string(255)
#  stop_command    :string(255)
#  visit_url       :string(255)
#  status_text     :text(65535)
#  branch_text     :text(65535)
#  notes           :string(255)
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#

class Project < ApplicationRecord
  require 'net/ssh'
  require 'timeout'
  delegate :bundle, :start_server, :assets, :migrate, :checkout, :pull, to: :do!

  has_many :operation_logs

  attr_accessor :commands

  def bundle
    add_cmd 'bundle', 'bundle'
  end

  def start_server
    add_cmd 'start_server', 'RAILS_ENV=production puma'
  end

  def assets
    add_cmd 'assets', 'RAILS_ENV=production rails assets:precompile'
  end

  def migrate
    add_cmd 'migrate', 'RAILS_ENV=production rails db:migrate'
  end

  def checkout(branch_name)
    branch_name.gsub!('origin/','')
    cmd = branch_info[:local].include?(branch_name) ? "git checkout #{branch_name}" : "git checkout -b #{branch_name} origin/#{branch_name}"
    add_cmd 'checkout', cmd
  end

  def pull
    add_cmd 'pull', 'git pull'
  end

  def add_cmd(name, command)
    self.commands ||= []
    self.commands << { name: name, command: command }
    self
  end

  def single_cmd(cmd, bash_login = true)
    bash_login ? "/bin/bash -l -c 'cd #{full_path} && #{cmd}'" : "cd #{full_path} && #{cmd}"
  end

  def update_branch_text!
    user, host = name_a_host.split('@')
    Net::SSH.start(host, user) do |ssh|
      ssh.exec! single_cmd('git fetch -p', false)
      self.update branch_text: ssh.exec!(single_cmd('git branch -a', false))
      self.update status_text_time: Time.now,
                  status_text: ssh.exec!(single_cmd("ps -aux | egrep \"`cat #{pid_path.presence||'tmp/pids/puma.pid'}`|PID\"", false))
    end
  end

  def do!
    user, host = name_a_host.split("@")
    Net::SSH.start(host, user) do |ssh|
      commands.each do |c|
        output = ssh.exec!(single_cmd(c[:command]))
        OperationLog.create(
            project_id: id,
            results: output,
            created_by: Session.current_user_id,
            command_text: c[:command],
            command_name: c[:name]
        )
      end
      # 执行以后更新分支信息
      ssh.exec! single_cmd('git fetch -p', false)
      self.update branch_text: ssh.exec!(single_cmd('git branch -a', false))

      OperationLog.create(
          project_id: id,
          results: '执行完毕',
          created_by: Session.current_user_id,
          command_text: "#{commands.map{|c|c[:name]}.join(',')} 完成",
          command_name: 'complete'
      )
    end
  end

  def status_info
    # status_text.to_s.split("\n").find_all{|x| (!x.include?('grep') && x.include?('puma')||x.include?('%CPU'))}.join("\n")
  end

  def branch_info
    return @branch_info if @branch_info.present?
    update_branch_text! if branch_text.blank?
    branches = branch_text.to_s.split("\n").map(&:strip).compact - ['']
    result = { local: [], remote: [] }
    branches.each do |b|
      if b.start_with?('*')
        result[:current] = b.gsub('* ','')
        result[:local] << result[:current]
      elsif b.start_with?('remotes/origin/HEAD')
        next
      elsif b.start_with?('remotes/origin/')
        result[:remote] << b.gsub('remotes/origin/','')
      else
        result[:local] << b
      end
    end
    @branch_info = result
  end

end
